package org.jeecg.common.file;

import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.mock.JeecgMockMultipartFile;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.text.SimpleDateFormat;

/**
 * 文件自定义处理
 * 包含：
 * 1. 文件类型、大小和安全性等限制
 * 2.上传途径分类：本地（deprecated）、MinIO（默认）、Ali OSS等扩展
 *
 * @author jiangtianyi
 * @version 1.0
 * @date 2023-03-02
 */
@Slf4j
@Component
public class MultipartFileCustomHandler {

    private final String uploadType;

    /**
     * 基于"类型"上传文件，支持方式：
     * 1. minio
     *
     * @author jiangtianyi
     * @since 1.0
     */
    public String upload() {
        HttpServletRequest httpServletRequest = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        String customPath = httpServletRequest.getParameter(FileRequestCommon.BIZ);

        // <漏洞修复>
        // 时间：2021-12-10
        // 作者：zhaowl
        // 描述：文件上传，如果biz为空则默认赋值，当前日期做为biz
        if (oConvertUtils.isEmpty(customPath)) {
            customPath = DateUtils.getDataString(new SimpleDateFormat("yyyyMMdd"));
        }
        // --- --- --- --- 结束 --- --- --- ---

        if (customPath.contains(SymbolConstant.SPOT_SINGLE_SLASH) || customPath.contains(SymbolConstant.SPOT_DOUBLE_BACKSLASH)) {
            throw new RuntimeException("非法上传目录格式");
        }
        MultipartHttpServletRequest multipartHttpServletRequest = FileRequestCommon.getMultipartHttpServletRequest();
        // 获取上传文件对象
        MultipartFile file = multipartHttpServletRequest.getFile(FileRequestCommon.FILE);

        // <漏洞修复>
        // 时间：2023-03-02
        // 作者：jiangtianyi
        // 描述：文件类型限制
        if (file == null) {
            throw new RuntimeException("上传文件不允许为空");
        }
        if (!FileTypeEnum.contains(file.getContentType())) {
            throw new RuntimeException("不允许上传此类型文件");
        }
        // --- --- --- --- 结束 --- --- --- ---

        // <功能优化>
        // 时间：2021-05-24
        // 作者：zhaowl
        // 描述：文件上传支持自定义文件名称
        String fileName = httpServletRequest.getParameter(FileRequestCommon.FILE_NAME);
        if (oConvertUtils.isNotEmpty(fileName)) {
            try {
                file = new JeecgMockMultipartFile(fileName, fileName, file.getContentType(), file.getBytes());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        // --- --- --- --- 结束 --- --- --- ---

        if (FileServerType.MINIO.equalsIgnoreCase(uploadType)) {
            return CommonUtils.upload(file, customPath, uploadType);
        }
        throw new RuntimeException("无可用的文件服务");
    }

    public MultipartFileCustomHandler(@Value("${jeecg.uploadType:minio}") String uploadType) {
        this.uploadType = uploadType;
    }
}